/* keyboard.c
 * By: Spencer Clark
 * Date created: March 18th 2011
 * Date modified: April 7th 2011
 * Modified by: Spencer Clark
 */

#include <sys/io.h>

#include <keyboard.h>
#include <interrupt.h>
#include <xxxio.h>

uint8_t keyboard_getc(void)
{
  uint8_t stat;
  uint8_t data;
  static uint8_t shift;

  /* Verify status */
  stat = inb(KBD_STAT_P);
  if (!(stat & KBD_IN_BUF)) {
    return 0;
  }
  
  /* grab the scancode for the keypress/release */
  data = inb(KBD_DATA_P); 

  /* Check if release */
  if (data & 0x80) { /* => high bit set, so this is a release */
    if (shiftcode[data & ~0x80]) {
      shift &= 0;
    }
    return 0;
  }

  /* Use ESC(0x1) key to demo our exception handler */
  if (0x1 == data) { /* cause a divide by zero exception when ESC pressed */
    data /= 0;
  }

  /* Check if shift is pressed. If so, use the shiftmap to determine char */
  shift |= shiftcode[data];
  if (shift) {
    return shiftmap[data];
  }

  /* If shift isn't being pressed use normalmap to determine the char */
  return normalmap[data];
}

void keyboard_int(void)
{
  xprintc(keyboard_getc());
}

static int_hook_t keyboard_hook;

void init_keyboard(void)
{
  set_int_handler(&keyboard_hook, KEYBOARD_INT, 0);
  enable_interrupt(&keyboard_hook);
}

void keyboard_handler()
{
  keyboard_int();
  eoi(KEYBOARD_INT);
}
